﻿using System;
using System.Data;
using Microsoft.Extensions.Configuration;

namespace Topro.Db
{
    /// <summary>
    /// 数据连接事务的Session接口
    /// </summary>
    public interface IDb : IDisposable
    {
        /// <summary>
        /// 连接对象
        /// </summary>
        IDbConnection DbConnection { get; }

        /// <summary>
        /// 事务对象
        /// </summary>
        IDbTransaction DbTransaction { get; }

        /// <summary>
        /// 开始事务
        /// </summary>
        /// <param name="isolation"></param>
        /// <returns></returns>
        IDbTransaction Begin(IDbConnection dbConnection, IsolationLevel isolation = IsolationLevel.Serializable);

        /// <summary>
        /// 提交事务
        /// </summary>
        void Commit();

        /// <summary>
        /// 回滚事务
        /// </summary>
        void Rollback();

        /// <summary>
        /// 释放资源
        /// </summary>
        void Dispose(bool disposed);
    }

    /// <summary>
    /// 数据库连接事务的Session对象
    /// </summary>
    public class Db:IDb
    {
        #region 字段
        /// <summary>
        /// 数据库连接对象
        /// </summary>
        private IDbConnection _dbConnection;

        /// <summary>
        /// 数据库事务对象
        /// </summary>
        private IDbTransaction _dbTransaction;

        /// <summary>
        /// 是否释放
        /// </summary>
        private bool _disposed = false;

        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        public static readonly string _connectionStrings = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build()["ConnectionStrings:mysqlconnection"];
        #endregion

        #region 属性
        /// <summary>
        /// 数据库连接对象
        /// </summary>
        public IDbConnection DbConnection
        {
            get { return _dbConnection; }
        }

        /// <summary>
        /// 数据库事务对象
        /// </summary>
        public IDbTransaction DbTransaction
        {
            get { return _dbTransaction; }
        }
        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        public Db()
        {
            //_dbConnection = new System.Data.SqlClient.SqlConnection(_connectionStrings);
            _dbConnection = new MySql.Data.MySqlClient.MySqlConnection(_connectionStrings);
        }

        /// <summary>
        /// 开启
        /// </summary>
        /// <param name="isolation"></param>
        /// <returns></returns>
        public IDbTransaction Begin(IDbConnection dbConnection, IsolationLevel isolation = IsolationLevel.Serializable)
        {
            if (dbConnection.State == ConnectionState.Closed)
            {
                dbConnection.Open();
            }

            return dbConnection.BeginTransaction(isolation);
        }

        /// <summary>
        /// 事务提交
        /// </summary>
        public void Commit()
        {
            _dbTransaction.Commit();
        }

        /// <summary>
        /// 事务回滚
        /// </summary>
        public void Rollback()
        {
            _dbTransaction.Rollback();
            _dbTransaction.Dispose();
        }

        /// <summary>
        /// 释放非托管资源
        /// </summary>
        ~Db()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose(bool disposed)
        {
            if (!_disposed)
            {
                if (_dbConnection != null)
                {
                    using (_dbConnection)
                    {
                        if (_dbConnection.State != ConnectionState.Closed)
                        {
                            if (_dbTransaction != null)
                            {
                                _dbTransaction.Rollback();
                                _dbTransaction.Dispose();
                            }
                        }
                        _dbConnection.Close();
                        _dbConnection.Dispose();
                    }
                }
                this._disposed = true;
            }
        }
    }
}
